package com.ruoyi.system.coretools.pay;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.http.OkHttpUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.common.utils.uuid.UUID;
import com.ruoyi.system.domain.TPayHistory;
import com.ruoyi.system.domain.TUserInfo;
import com.ruoyi.system.mapper.TPayHistoryMapper;
import com.ruoyi.system.mapper.TUserInfoMapper;
import com.ruoyi.system.service.ISysConfigService;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;

@Component
public class PayUtils {
    @Autowired
    TPayHistoryMapper tPayHistoryMapper;
    @Autowired
    TUserInfoMapper tUserInfoMapper;
    private static final Logger log = LoggerFactory.getLogger(PayUtils.class);
    //payUrl后面做成配置
    public static String agentId = "";
    //支付地址前缀
    public static String payUrl = "";
    //回调地址url
    public static String callbackUrl = "";
    //apiKey
    public static String apiKey = "";


    public PayUtils() {
        ISysConfigService configService = SpringUtils.getBean(ISysConfigService.class);
        agentId = configService.selectConfigByKey("pay.config.agentId");
        payUrl = configService.selectConfigByKey("pay.config.payUrl");
        callbackUrl = configService.selectConfigByKey("pay.config.callbackUrl");
        apiKey = configService.selectConfigByKey("pay.config.apiKey");
    }


    /**
     * 充值
     * /pay
     * ```
     * - 请求参数
     * - agent_id(代理id)(string)
     * - user_id(用户id)(string)
     * - order_id(订单id)(string)
     * - amount(金额)(float)
     * - url(回调地址)(string)
     * - time(时间戳)(int)
     * - sign(签名,md5(agent_id+API_KEY+time+user_id+order_id))(string)()
     * <p>
     * - 返回示例
     * -
     * ```
     * {
     * "state": 1,
     * "text": "订单创建成功"
     * }
     * ```
     */
    @Transactional
    public String createChongzhiOrder(long userId, float amount) throws Exception {

        log.info("收到发起收款原始请求:userId:{} orderId:{} amount:{}", userId, amount);
        //10位时间戳
        int time = (int) (System.currentTimeMillis() / 1000);

        JSONObject param = new JSONObject();
        param.put("agent_id", agentId);
        param.put("user_id", userId);
        String orderId = UUID.randomUUID().toString();
        param.put("order_id", orderId);
        param.put("amount", amount);
        param.put("url", callbackUrl);
        param.put("time", time);
        //构建签名
        String signString = agentId + apiKey + time + userId + orderId;
        String md5Hash = DigestUtils.md5Hex(signString);
        log.info("MD5 Hash:{}", md5Hash);
        param.put("sign", md5Hash);


        //入库记录，用于回调变更确认。
        TPayHistory tPayHistory = new TPayHistory();
        tPayHistory.setAgentId(agentId);
        tPayHistory.settUserId(userId);
        tPayHistory.setOrderId(orderId);
        tPayHistory.setAmount(new BigDecimal(amount));
        tPayHistory.setUrl(callbackUrl);
        tPayHistory.setTime(time);
        tPayHistory.setOperationType(1);
        tPayHistory.setOperationStatus(0);
        tPayHistory.setOperationDescription("充值");
        tPayHistory.setUserId(userId + "");
        tPayHistoryMapper.insertTPayHistory(tPayHistory);


        //用户表金额加上
        TUserInfo tUserInfo = tUserInfoMapper.selectTUserInfoById(tPayHistory.gettUserId());
        //减去更新金额
        tUserInfo.setMoney(tUserInfo.getMoney() == null ? new BigDecimal(amount) : tUserInfo.getMoney().add(tPayHistory.getAmount()));
        //更新金额
        tUserInfoMapper.updateById(tUserInfo);

        try {
            //在此处编写要执行的任务代码
            String result = OkHttpUtils.builder().url(payUrl + "/pay")
                    .addHeader("Content-Type", "application/json; charset=utf-8")
                    .postJson(true, param.toJSONString())
                    .sync();
            log.info("支付接口返回的原始报文:{}", result);
            JSONObject jsonObject = JSON.parseObject(result);
            if (jsonObject.getIntValue("state") == 1) {
                //获取收银台url
                String shouyintaiUrl = jsonObject.getJSONObject("data").getString("url");
                log.info("支付接口返回的原始报文:{}", shouyintaiUrl);
                //拿到收款地址
                return shouyintaiUrl;
            }
        } catch (Exception e) {
            throw new ServiceException("三方充值接口调用失败", HttpStatus.ERROR);
        }


        return null;

    }


    /**
     * 查询充值状态
     * /pay
     * ```
     * - 请求参数
     * - agent_id(代理id)(string)
     * - order_id(订单id)(string)
     * <p>
     * - 返回示例
     * -
     * ```
     * {
     * "state": 1,//0代表未完成,1代表成功,2代表失败
     * "text": "支付成功",
     * "data": {
     * "id": 1,
     * "order_id": "123",
     * "user_id": "123",
     * "agent_id": "123",
     * "tron_address": "TdeEf45...",//收款的地址
     * "amount": 123,//应收金额
     * "time": 1712549570,//订单开始时间
     * "time_end":1712553170,//订单结束收款时间
     * "last_balance": 0,  //收款地址在收款前的余额
     * "balance": 123,   //收款地址收款后的余额
     * "state": 1
     * }
     * }
     * ```
     */
    public JSONObject queryChongzhiOrderStatus(String orderId) {
        try {
            log.info("收到发起查充值状态原始请求:orderId:{} ", orderId);

            JSONObject param = new JSONObject();
            param.put("agent_id", agentId);
            param.put("order_id", orderId);

            //在此处编写要执行的任务代码
            String result = OkHttpUtils.builder().url(payUrl + "/pay")
                    .addHeader("Content-Type", "application/json; charset=utf-8")
                    .postJson(true, param.toJSONString())
                    .sync();
            log.info("支付接口返回的原始报文:{}", result);
            JSONObject jsonObject = JSON.parseObject(result);
            if (jsonObject.getIntValue("state") == 1) {
                //获取收银台url
                JSONObject resultData = jsonObject.getJSONObject("data");
                log.info("支付接口返回的原始报文:{}", resultData);
                //拿到收款地址
                return resultData;
            }

        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("查询充值失败", HttpStatus.ERROR);
        }
        return null;

    }


    /**
     * 提现
     * /issue
     * ```
     * - 请求参数
     * - agent_id(代理id)(string)
     * - issue_id(下发订单id)(string)
     * - user_id(用户id)(string)
     * - amount(下发金额)(float)
     * - address_user(用户的收款地址)(string)
     * - time(时间戳,整数秒时间戳)(int)
     * - sign(签名,md5(agent_id+API_KEY+time+user_id+issue_id+amount))(string)
     * <p>
     * - 返回示例
     * -
     * ```
     * {
     * "state": 1,//0代表失败,1代表成功
     * "text": "订单创建成功"
     * }
     * ```
     */
    @Transactional
    public Boolean createTiXianOrder(long userId, float amount, String address_user) throws Exception {
        //提现的时候真正到款要减去平台提现手续费
        ISysConfigService configService = SpringUtils.getBean(ISysConfigService.class);
        String embodyMoney = configService.selectConfigByKey("embodyMoney");
        String vipEmbodyMoney = configService.selectConfigByKey("vipEmbodyMoney");
        double shouxufei=0;

        //检查vip适配手续费
        TUserInfo tUserInfo = tUserInfoMapper.selectTUserInfoById(userId);
        boolean isVip=tUserInfo.getVipId()!=null&&tUserInfo.getVipId().longValue()!=0?true:false;
        if(isVip) {
             shouxufei = amount * Double.parseDouble(vipEmbodyMoney);
        }else{
             shouxufei = amount * Double.parseDouble(embodyMoney);
        }


        log.info("收到发起提现原始请求:userId:{} issueId:{} amount:{} address_user:{}", userId, amount, address_user);
        //10位时间戳
        int time = (int) (System.currentTimeMillis() / 1000);

        JSONObject param = new JSONObject();
        param.put("agent_id", agentId);
        param.put("user_id", userId);
        String issueId = UUID.randomUUID().toString();
        param.put("issue_id", issueId);
        param.put("amount", amount-shouxufei);//真正提现算了手续费的
        param.put("url", callbackUrl);
        param.put("time", time);
        //构建签名
        String signString = agentId + apiKey + time + userId + issueId + amount;
        String md5Hash = DigestUtils.md5Hex(signString);
        log.info("MD5 Hash:{}", md5Hash);
        param.put("sign", md5Hash);

        insertTiXianPayHistoryInfo(userId, amount, time, issueId, md5Hash);


        try {
            //在此处编写要执行的任务代码
            String result = OkHttpUtils.builder().url(payUrl + "/issue")
                    .addHeader("Content-Type", "application/json; charset=utf-8")
                    .postJson(true, param.toJSONString())
                    .sync();
            log.info("支付接口返回的原始报文:{}", result);
            JSONObject jsonObject = JSON.parseObject(result);
            if (jsonObject.getIntValue("state") == 1) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            throw new ServiceException("三方提现接口调用失败", HttpStatus.ERROR);
        }


    }

    @Transactional
    public void insertTiXianPayHistoryInfo(long userId, float amount, int time, String issueId, String sign) throws Exception {

        //先校验余额够不够
        //多一个冻结金额动作
        TUserInfo tUserInfo = tUserInfoMapper.selectTUserInfoById(userId);

        if (tUserInfo.getMoney() == null || tUserInfo.getMoney().compareTo(new BigDecimal(amount)) == -1) {
            throw new ServiceException("提现失败,用户充值剩余的账户余额小于提现金额");
        }


        //入库
        TPayHistory tPayHistory = new TPayHistory();
        tPayHistory.setAgentId(agentId);
        tPayHistory.settUserId(userId);
        tPayHistory.setOrderId(issueId);
        tPayHistory.setAmount(new BigDecimal(amount));
        tPayHistory.setUrl(callbackUrl);
        tPayHistory.setTime(time);
        tPayHistory.setOperationType(2);
        tPayHistory.setOperationStatus(0);
        tPayHistory.setOperationDescription("充值");
        tPayHistory.setUserId(userId + "");
        tPayHistory.setSign(sign);
        tPayHistoryMapper.insertTPayHistory(tPayHistory);


        //减去更新金额
        tUserInfo.setMoney(tUserInfo.getMoney().subtract(tPayHistory.getAmount()));
        //加上更新冻结金额
        tUserInfo.setFreezMoney(tUserInfo.getFreezMoney().add(tPayHistory.getAmount()));//冻结金额+第二笔提现的冻结金额
        tUserInfoMapper.updateById(tUserInfo);
    }


    /**
     * 查询提现状态
     * /issue_info
     * ```
     * - 请求参数
     * - agent_id(代理id)(string)
     * - issue_id(下发订单id)(string)
     *
     * <p>
     * - 返回示例
     * -
     * ```
     * {
     * "state": 4,//1=等待审核,2=审核通过,3=正在下发,4=下发成功
     * "text": "下发成功",
     * "data": {
     * "id": 1,
     * "issue_id": "123",
     * "user_id": "123",
     * "agent_id": "123",
     * "time": 1712549570,
     * "amount": 123,//下发金额
     * "state":4,
     * "address_user":"TdeEf45...",//客户的地址,
     * "address_agent":"TEdfs2..."//下发的主地址
     * }
     * }
     * ```
     */
    public JSONObject queryTiXianOrderStatus(String issueId) {
        try {
            log.info("收到发起查提现状态原始请求:issueId:{} ", issueId);

            JSONObject param = new JSONObject();
            param.put("agent_id", agentId);
            param.put("issue_id", issueId);

            //调提现接口
            String result = OkHttpUtils.builder().url(payUrl + "/issue_info")
                    .addHeader("Content-Type", "application/json; charset=utf-8")
                    .postJson(true, param.toJSONString())
                    .sync();
            log.info("支付接口返回的原始报文:{}", result);
            JSONObject jsonObject = JSON.parseObject(result);
            if (jsonObject.getIntValue("state") == 1) {
                log.info("查询提现状态返回的原始报文:{}", jsonObject);
                return jsonObject;
            }

        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("查询提现失败", HttpStatus.ERROR);
        }
        return null;

    }


}
